package kamkor.webtools.url

import scala.util.matching.Regex.Match
import java.util.regex.Matcher

/**
 * Class for adding and removing tags to urls
 * 
 * Most forum open and enclosing (end) tags are suppoused, ie:
 * [img][/img] [url][/url] [youtube][/youtube]
 * 
 * If you want to use [url= and ][/url] it will work too. ie, http://www.d.pl/p.jpg will be [url="http://www.d.pl/p.jpg"][/url]
 * 
 * Most html tags should work fine as well. For example:
 * 
 * <img src=" and "/>
 * <a href=" and " target="_blank"/> 
 * 
 * In current version urls can't contain those characters: space, [ ] < > "
 *  
 * @author kamkor
 *
 */
object UrlTagger {	
	
	/** [url="http://somehost.com"]allowedCharsInBeetwenTags[/url] */
	private val allowedCharsInBeetwenForumTags = """[^\[\]]"""
		
	/** <img src="...">something something</img> */
	private val allowedCharsInBeetwenHtmlTags = """[^<>]"""
	
	/** ie. [img]http://www.d.pl/p/a/t/h/file.jpg[/img] */
	private val urlInForumTagsPattern = """(\[[\w\."'=]+\])?"""+ UrlPatterns.hostAndPathAndFilePattern +"""(\[/\w+\])?"""	
	/** ie. [url="http://www.page.com/s.wmv"]super movie[/url] */
	private val urlInForumTagsPattern2 = """(\[[\w\."'=]+\")?"""+ UrlPatterns.hostAndPathAndFilePattern +"""("\]"""+ allowedCharsInBeetwenForumTags +"""*\[/\w+\])?"""
	
	/** ie. <img src="http://www.d.pl/p/a/t/h/file.jpg"/> */
	private val urlInHtmlTagsPattern = """(<[\w\s"'={}\.]+")?"""+ UrlPatterns.hostAndPathAndFilePattern +"""("[\w\s"'={}\.]*/>)?"""
	/** 
	 * ie <img src="http://www.d.pl/p/a/t/h/file.jpg">image</img>, {1} is used for open and end tag to differ this pattern from above 
	 * Otherwise it would also match <img src="http://www.d.pl/p/a/t/h/file.jpg">image</img> as <img src="http://www.d.pl/p/a/t/h/file.jpg">image
	 */   
	private val urlInHtmlTagsPattern2 = """(<[\w\s"'={}\.]+"){1}"""+ UrlPatterns.hostAndPathAndFilePattern +"""("[\w\s"'={}\.]*>"""+ allowedCharsInBeetwenHtmlTags +"""*</\w+>){1}"""	
	
	private val urlInTagsPattern = urlInForumTagsPattern +"|"+ urlInForumTagsPattern2 +"|"+ urlInHtmlTagsPattern2 +"|"+ urlInHtmlTagsPattern 	
	
	/**	 
	 * @param text with urls
	 * @return text with urls wrapped in img tags 
	 */
	def addImgTags(text: String): String = {
		addTags(text, "[img]", "[/img]")
	}
	
	/** 
	 * @param text with urls
	 * @return text with urls with specified extensions, wrapped in img tags
	 */
	def addImgTags(text: String, extensions: Array[String]): String = {
		addTags(text, "[img]", "[/img]", extensions)
	}
	
	/**
	 * @param text with urls
	 * @param openTag for example [img]
	 * @param endTag for example [/img]
	 * @return text with urls wrapped in tags
	 */
	def addTags(text: String, openTag: String, endTag: String): String = {	
		urlInTagsPattern.r.replaceAllIn(text, m => { 
			val url = m.toString()			
			if ((url.startsWith("[") && url.endsWith("]")) || (url.startsWith("<") && url.endsWith(">")))
				Matcher.quoteReplacement(url)
			else
				Matcher.quoteReplacement(openTag + url + endTag)
		})		
	}
	
	/**
	 * @param text with urls
	 * @param openTag for example [img]
	 * @param endTag for example [/img]
	 * @param extensions for example Array("jpg", "png", "gif")
	 * @return text with urls with specified extensions, wrapped in tags
	 */
	def addTags(text: String, openTag: String, endTag: String, extensions:Array[String]): String = {		
		urlInTagsPattern.r.replaceAllIn(text, m => { 
			val url = Matcher.quoteReplacement(m.toString)			
			if ((url.startsWith("[") && url.endsWith("]")) || (url.startsWith("<") && url.endsWith(">"))) {			
				url	
			}
			else {
				val urlTagged = 
					for (
						ext <- extensions 
						if url.matches("""(?i).*"""+ ext +"""$""")
					) yield (openTag + url + endTag)									
				if (urlTagged.length == 1) Matcher.quoteReplacement(urlTagged(0)) else url	
			}
		})		
	}

	/**
	 * Removes tags from urls that are in text and returns updated text. Tags are not case sensitive.
	 * 
	 * @param text with urls
	 * @param openTag for example [img]
	 * @param endTag for example [/img]
	 * @return text with removed tags
	 */
	def removeTags(text: String, openTag: String, endTag: String): String = {		
		val openTagPattern = precedeMetacharsWithBackslash(openTag)
		val endTagPattern = precedeMetacharsWithBackslash(endTag)		
		val pattern = "(?i)"+ openTagPattern +"""|"""+ endTagPattern	
		
		urlInTagsPattern.r.replaceAllIn(text, m => {
			val url = Matcher.quoteReplacement(m.toString)
			if(url.matches("(?i)^" + openTagPattern +".+"+ endTagPattern +"$")) url.replaceAll(pattern, "") else url			
		})	
	}	
	
	/**
	 * Tags from urls that end with specified extensions will be removed only. Tags are not case sensitive.
	 * 
	 * @param text with urls
	 * @param openTag for example [img]
	 * @param endTag for example [/img]
	 * @param extensions for example Array("jpg", "png", "gif")
	 * @return text with removed tags from urls with specified extensions
	 */
	def removeTags(text: String, openTag: String, endTag: String, extensions: Array[String]): String = {
		val openTagPattern = precedeMetacharsWithBackslash(openTag)
		val endTagPattern = precedeMetacharsWithBackslash(endTag)	
		val pattern = "(?i)"+ openTagPattern +"""|"""+ endTagPattern

		// remove tags from those urls, who end with specified extensions only
		urlInTagsPattern.r.replaceAllIn(text, m => {
			val url = Matcher.quoteReplacement(m.toString)						
			val urlWithoutTags =
				for (
					ext <- extensions
					if url.matches("""(?i)^"""+ openTagPattern +""".*"""+ ext + endTagPattern + """$""")
				) yield url.replaceAll(pattern, "")				
			if (urlWithoutTags.length == 1) urlWithoutTags(0) else url
		})
	}	
	
	/**
	 * @return tag with metachars preceeded with backslash
	 */
	private def precedeMetacharsWithBackslash(tag: String) = tag.replaceAll("""\[""", """\\[""").replaceAll("""\]""", """\\]""")
	
}